using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;

namespace JlPay.Sdk.Core
{
    /// <summary>
    /// 默认HTTP客户端实现
    /// </summary>
    public class DefaultHttpClient : IHttpClient, IDisposable
    {
        private readonly HttpClient _httpClient;
        private readonly Config _config;
        private bool _disposed = false;

        /// <summary>
        /// 创建默认HTTP客户端
        /// </summary>
        /// <param name="config">配置对象</param>
        /// <param name="connectTimeout">连接超时时间</param>
        /// <param name="readTimeout">读取超时时间</param>
        public DefaultHttpClient(Config config, TimeSpan connectTimeout, TimeSpan readTimeout)
        {
            _config = config ?? throw new ArgumentNullException(nameof(config));
            var handler = new HttpClientHandler();
            
            _httpClient = new HttpClient(handler)
            {
                Timeout = readTimeout
            };
        }

        /// <summary>
        /// 创建默认HTTP客户端（使用默认超时）
        /// </summary>
        /// <param name="config">配置对象</param>
        public DefaultHttpClient(Config config) : this(config, TimeSpan.FromSeconds(30), TimeSpan.FromSeconds(60))
        {
        }

        /// <summary>
        /// 执行HTTP请求
        /// </summary>
        /// <param name="request">HTTP请求对象</param>
        /// <returns>HTTP响应对象</returns>
        public async Task<HttpResponse> ExecuteAsync(HttpRequest request)
        {
            if (_disposed)
                throw new ObjectDisposedException(nameof(DefaultHttpClient));

            string? reqBodyStr = null;
            HttpContent? content = null;

            // 处理请求体
            if (request.Body != null)
            {
                // 如果已经是HttpContent类型（如MultipartFormDataContent），直接使用
                if (request.Body is HttpContent httpContent)
                {
                    content = httpContent;
                    reqBodyStr = "[MultipartFormDataContent]"; // 用于调试显示
                }
                else
                {
                    try
                    {
                        reqBodyStr = JsonSerializer.Serialize(request.Body, new JsonSerializerOptions
                        {
                            PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
                            WriteIndented = false,
                            Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping // 不转义Unicode字符
                        });
                        content = new StringContent(reqBodyStr, Encoding.UTF8, "application/json");
                    }
                    catch (Exception ex)
                    {
                        throw new InvalidOperationException($"序列化请求体失败: {ex.Message}", ex);
                    }
                }
            }

            HttpRequestMessage httpRequest;
            try
            {
                httpRequest = new HttpRequestMessage(new HttpMethod(request.Method), request.Url)
                {
                    Content = content
                };
            }
            catch (Exception ex)
            {
                content?.Dispose();
                throw new InvalidOperationException($"创建HTTP请求失败: {ex.Message}", ex);
            }

            // 设置请求头
            foreach (var header in request.Headers)
            {
                try
                {
                    if (header.Key.Equals("Content-Type", StringComparison.OrdinalIgnoreCase))
                    {
                        // 对于multipart/form-data，Content-Type由MultipartFormDataContent自动设置
                        // 对于JSON请求，Content-Type通过StringContent设置
                        // 跳过手动设置
                        continue;
                    }
                    httpRequest.Headers.Add(header.Key, header.Value);
                }
                catch (Exception)
                {
                    // 某些头部可能不能直接添加，忽略错误
                }
            }

            // 打印请求信息
            if (_config.Debug)
            {
                Console.WriteLine($"请求URL: {request.Url}");
                Console.WriteLine($"请求方法: {request.Method}");
                Console.WriteLine($"请求头: {JsonSerializer.Serialize(request.Headers)}");
                if (!string.IsNullOrEmpty(reqBodyStr))
                {
                    Console.WriteLine($"请求体: {reqBodyStr}");
                }
            }

            HttpResponseMessage httpResponse;
            try
            {
                // 执行请求
                httpResponse = await _httpClient.SendAsync(httpRequest);
            }
            catch (Exception ex)
            {
                httpRequest.Dispose();
                throw new InvalidOperationException($"执行HTTP请求失败: {ex.Message}", ex);
            }

            try
            {
                // 读取响应体
                string bodyString = await httpResponse.Content.ReadAsStringAsync();

                // 处理响应头
                var headers = new Dictionary<string, string>();
                foreach (var header in httpResponse.Headers)
                {
                    if (header.Value != null)
                    {
                        headers[header.Key] = string.Join(", ", header.Value);
                    }
                }
                
                // 添加Content headers
                foreach (var header in httpResponse.Content.Headers)
                {
                    if (header.Value != null)
                    {
                        headers[header.Key] = string.Join(", ", header.Value);
                    }
                }

                // 打印响应信息
                if (_config.Debug)
                {
                    Console.WriteLine($"响应状态码: {(int)httpResponse.StatusCode}");
                    Console.WriteLine($"响应头: {JsonSerializer.Serialize(headers)}");
                    Console.WriteLine($"响应体: {bodyString}");
                }

                // 构建响应
                var response = new HttpResponse
                {
                    StatusCode = (int)httpResponse.StatusCode,
                    Headers = headers,
                    Body = bodyString
                };

                return response;
            }
            finally
            {
                httpRequest.Dispose();
                httpResponse.Dispose();
            }
        }

        /// <summary>
        /// 释放资源
        /// </summary>
        public void Dispose()
        {
            if (!_disposed)
            {
                _httpClient?.Dispose();
                _disposed = true;
            }
        }
    }
} 